package com.cupdata.zicon.jdk7concurrent.chapter4;

import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 
 * 是否添加 executor.awaitTermination 打出的Rejected信息是有区别的
 * 
 * When an executor receives a task to execute, it checks if the shutdown()
 * method has been called. If so, it rejects the task. First, it looks for the
 * handler established with setRejectedExecutionHandler(). If there's one, it
 * calls the rejectedExecution() method of that class, otherwise it throws
 * RejectedExecutionExeption. This is a runtime exception, so you don't need to
 * put a catch clause to control it.
 * 
 * 
 * @author SunYabing
 *
 */
public class RejectedTaskControllerTest {

	public RejectedTaskControllerTest() {

	}

	public static void main(String[] args) {
		RejectedTaskController controller = new RejectedTaskController();
		ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors
				.newCachedThreadPool();
		executor.setRejectedExecutionHandler(controller);
		System.out.printf("Main: Starting.\n");

		for (int i = 0; i < 3; i++) {
			Task4321 task = new Task4321("Task" + i);
			executor.submit(task);
		}

		System.out.printf("Main: Shutting down the Executor.\n");
		executor.shutdown(); // Shutting down, pool size = 3, active threads =
								// 3, queued tasks = 0, completed tasks = 0
		// try {
		// executor.awaitTermination(1, TimeUnit.HOURS);
		// } catch (InterruptedException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// }//Terminated, pool size = 0, active threads = 0, queued tasks = 0,
		// completed tasks = 3

		System.out.printf("Main: Sending another Task.\n");
		Task4321 task = new Task4321("RejectedTask");
		executor.submit(task);
		System.out.println("Main: End");
		System.out.printf("Main: End.\n");

	}

}

class RejectedTaskController implements RejectedExecutionHandler {

	@Override
	public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
		System.out.printf(
				"RejectedTaskController: The task %s hasbeen rejected\n",
				r.toString());
		System.out.printf("RejectedTaskController: %s\n", executor.toString());
		System.out.printf("RejectedTaskController: Terminating:%s\n",
				executor.isTerminating());
		System.out.printf("RejectedTaksController: Terminated:%s\n",
				executor.isTerminated());
	}
}

class Task4321 implements Runnable {
	private String name;

	public Task4321(String name) {
		this.name = name;
	}

	@Override
	public void run() {
		System.out.println("Task " + name + ": Starting");
		try {
			long duration = (long) (Math.random() * 10);
			System.out
					.printf("Task %s: ReportGenerator: Generating areport during %d seconds\n",
							name, duration);
			TimeUnit.SECONDS.sleep(duration);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.printf("Task %s: Ending\n", name);
	}

	public String toString() {
		return name;
	}
}
